// 实现这个项目的构建任务

const { src, dest, parallel, series, watch } = require("gulp");
const del = require("del");

const browserSync = require("browser-sync");
const bs = browserSync.create();

// 自动加载插件
const loadPlugins = require("gulp-load-plugins");
const plugins = loadPlugins();

// 构建任务所需要的一些配置数据
const data = {
  menus: [
    {
      name: "Home",
      icon: "aperture",
      link: "index.html",
    },
    {
      name: "Features",
      link: "features.html",
    },
    {
      name: "About",
      link: "about.html",
    },
    {
      name: "Contact",
      link: "#",
      children: [
        {
          name: "Twitter",
          link: "https://twitter.com/w_zce",
        },
        {
          name: "About",
          link: "https://weibo.com/zceme",
        },
        {
          name: "divider",
        },
        {
          name: "About",
          link: "https://github.com/zce",
        },
      ],
    },
  ],
  pkg: require("./package.json"),
  date: new Date(),
};

// 构建html页面文件 - 插件gulp-swig（swig模板引擎转换插件）
const page = () => {
  return src("src/*.html", { base: "src" })
    .pipe(plugins.swig({ data, defaults: { cache: false } })) // 将swig选项中的 cache 设置为 false，防止swig模板缓存导致页面不能及时更新
    .pipe(dest("temp"))
    .pipe(bs.reload({ stream: true }));
};

// 构建style样式文件 - 插件gulp-sass
// sass模块工作时， 会把名字以 _ 开头的样式文件当作在主文件中依赖的文件，不会被转化构建
const style = () => {
  return src("src/assets/styles/*.scss", { base: "src" })
    .pipe(plugins.sass({ outputStyle: "expanded" }))
    .pipe(dest("temp"))
    .pipe(bs.reload({ stream: true }));
};

// 构建script脚本文件 - 插件gulp-babel、 同时还需要安装 @babel/core @babel/preset-env
const script = () => {
  return src("src/assets/scripts/*.js", { base: "src" })
    .pipe(plugins.babel({ presets: ["@babel/preset-env"] }))
    .pipe(dest("temp"))
    .pipe(bs.reload({ stream: true }));
};

// 构建image图片 - 插件gulp-imagemin - 即无损压缩文件
const image = () => {
  return src("src/assets/images/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};
// 构建font字体
const font = () => {
  return src("src/assets/fonts/**", { base: "src" })
    .pipe(plugins.imagemin())
    .pipe(dest("dist"));
};

// 构建public额外的一些其它文件
const extra = () => {
  return src("public/**", { base: "public" }).pipe(dest("dist"));
};

// 热更新 开发服务环境 - 插件browser-sync（非gulp插件，在这里需要gulp管理）
const serve = () => {
  // watch 监视路径下文件的变动，并执行对应的构建任务
  watch("src/assets/styles/*.scss", style);
  watch("src/assets/scripts/*.js", script);
  watch("src/*.html", page);
  // 监听文件变化，并通过 bs.reload更新到浏览器
  watch(
    ["src/assets/images/**", "src/assets/fonts/**", "public/**"],
    bs.reload
  );

  // 初始化服务的相关配置
  bs.init({
    notify: false, // 关闭启动页面上 browser-sync是否连接的小提示
    port: 2080, // 启动端口号
    open: true, // 是否自动打开浏览器（默认true）
    // files: "dist/**", // 服务启动后，自动监听该目录下文件的改动，同步浏览器（指定了 bs.reload 就不需要配置该项了）
    server: {
      baseDir: ["temp", "src", "public"], // 网站服务的根目录（按顺序逐级查找文件）
      routes: {
        "/node_modules": "node_modules",
      }, // 将匹配的路径 对应到指定的目录
    },
  });
};

// useref 文件引用处理 - 插件gulp-useref
const useref = () => {
  return (
    src("temp/*.html", { base: "temp" })
      .pipe(plugins.useref({ searchPath: ["temp", "."] }))
      // html js css
      .pipe(plugins.if(/\.js$/, plugins.uglify()))
      .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
      .pipe(
        plugins.if(
          /\.html$/,
          plugins.htmlmin({
            collapseWhitespace: true, // 压缩html中的空格符、换行符
            minifyCSS: true, // 压缩html中的css
            minifyJS: true, // 压缩html中的js
          })
        )
      )
      .pipe(dest("dist"))
  );
};

// 文件清除 - 插件del
const clean = () => {
  return del(["dist", "temp"]);
};

// 组合构建任务 - parallel 同时开始执行（并行任务）
const compile = parallel(style, script, page);

// 开发环境下执行的任务 - series 按顺序逐个执行（串行任务）
// 先将执行基础的构建任务，再去执行 开发环境所需的热更新服务
const develop = series(compile, serve);

// 上线之前执行的任务
const build = series(
  clean,
  parallel(series(compile, useref), image, font, extra)
);

module.exports = {
  clean,
  develop,
  build,
};
